/*
 * @Description:
 * @Autor: Bingo
 * @Date: 2024-08-29 16:21:56
 * @LastEditors: Bingo
 * @LastEditTime: 2024-09-02 15:50:07
 */
import { Router } from "vue-router";
import { useCookies } from "vue3-cookies";
// 加载进度条插件
import nprogress from "nprogress"; // progress bar
import "nprogress/nprogress.css"; // progress bar style
import Modal from "ant-design-vue/es/modal";

import { setDocumentTitle, domTitle } from "@/utils/dom_utils";
import { utilGetPageAuths } from "@/utils/common";
import { ACCESS_TOKEN, USER_MENU } from "@/config/const";
import { useStore } from "vuex";

import { autoLoginRoutes } from "./route_list";
import {
  routerTree,
  createMenuRouter,
  layoutRouterItem,
  getPathName,
} from "./route_utils";

import routerInstance from "./index";

const Store = useStore();
const { cookies } = useCookies();
const routeSafe = (router: Router) => {
  // 免密校验的页面配置  用的是route Item中的name 进行匹配
  const WHITE_LIST: any[] = [
    "home",
    "login",
    "register",
    "supplier",
    "registerResult",
    "taskcreation",
    "start",
    "password",
    "basicInformationpc",
  ];

  nprogress.configure({
    showSpinner: false,
  });
  /* 
    路由守卫  每次切换url都会触发 哪怕是本身
    这里仅做了登录处理
  */

  // 路由跳转监听  每次跳转都会进来包括当前页面刷新
  router.beforeEach(
    /* 
    to 表示要去的页面也就是当前进入的路由  
    from 表示从哪个路由跳转
    next 渲染的开关 如果next不执行或者传入false则禁止进入该路由！
  */
    async (to: any, from: any, next: (arg0?: any | undefined) => void) => {
      // 进度条开启
      nprogress.start();
      // 页面置顶
      document.body.scrollTop = 0;
      // 设置当前页面的title
      to.meta &&
        typeof to.meta.title !== "undefined" &&
        setDocumentTitle(`${to.meta.title} - ${domTitle}`);

      // 登录凭证
      let envType;
      console.log(
        "-------------------我进来了router before---------------------"
      );
      // console.log('process.env.NODE_ENV = ', process.env.NODE_ENV)
      // console.log('from = ', from)
      // console.log('to = ', to)

      // 开发环境 仅考虑从本地获取登录凭证
      if (process.env.NODE_ENV === "development") {
        console.log("-------------------我是development---------------------");
        envType = localStorage.getItem(ACCESS_TOKEN);

        // 生产环境 除了考虑本地获取登录凭证 还要 考虑从erp等其他系统单点进来的
        // 这里涉及到 同域名共享Cookies的机制
      } else {
        let LtpaToken = cookies.get("LtpaToken");
        let LtStorage = sessionStorage.getItem("LtpaToken");
        // 注意 手动登录 和 EIP跳入都会往cookies中写值  其实这里只对eip跳入的做了限制  手动登录的过期是通过请求了接口 后台控制了
        // envType 就是判断是否cookies和storage都存在值的情况
        envType =
          cookies.isKey("LtpaToken") &&
          LtpaToken !== "null" &&
          LtpaToken &&
          (localStorage.getItem(ACCESS_TOKEN) ||
            localStorage.getItem("pro__Access-Token"));

        /* 
        生产环境下 
        登录过期情况的逻辑处理  
        主要是处理单点跳过来过期问题
        判断依据： cookies和存储的不一致则判定登录失效
      */

        if (
          envType &&
          LtStorage &&
          LtStorage !== LtpaToken &&
          !Store.state.app.key
        ) {
          // 退出登录
          Store.state.app.key = true;
          console.log(
            "------------------------cookies和存储的不一致-----------------------------------"
          );

          // 判断是否要进入的是自动登录的页面
          let needAutoIndex = autoLoginRoutes.find((item) => {
            return item.path === to.path;
          });
          // 1.如果是自动登录的页面则先退出登录 然后再自动登录
          if (needAutoIndex) {
            // 需要自动登录的路由不需要弹窗
            Store.dispatch("user/Logout", false).then(() => {
              Store.state.app.key = false;
              // 刷新页面会重新走before逻辑
              location.reload();
            });
            // 2.非自动登录的
          } else {
            console.log(
              "-------------登录已过期， 需要重新登录------------------"
            );

            // 非自动登录的 弹出 登录过期 提示框
            Modal.warning({
              title: "提示",
              content: "登录已过期， 需要重新登录",
              okText: "确认",
              onOk() {
                Store.dispatch("user/Logout", false).then(() => {
                  Store.commit("app/CLOSE_KEY");
                  // location.reload();
                });
              },
            });
            console.log(
              "------------------------报错22222-----------------------------------"
            );
          }
        }
      }

      /* 
      开发环境下 有登录的凭证则可以跳转
      生产环境下 有登录凭证 且 未过期
    */
      if (envType) {
        /* 
        has token 
        已经登录跳登录页则回调到首页
      */
        if (to.path === "/user/login") {
          next({
            path: "/home",
          });
          nprogress.done();
          // 跳其他页  则判断是否需要获取菜单权限等信息
          // 登录和获取菜单列表是分开 因此先登录获取Tk 再获取菜单 生成路由表
        } else {
          console.log(
            "--------------- 已经登录跳其他页------------------------"
          );
          // 1.没有生成菜单列表 即刚登录进来时 需调接口获取动态路由表
          if (Store.getters.userMenu.length === 0) {
            // 获取用户信息 并存储在store里
            Store.dispatch("user/GetInfo");
            // 获取用户部门信息 并存储在store里
            Store.dispatch("user/GetDeptList");
            console.log(
              "--------------- store.getters.userMenu.length === 0------------------------"
            );

            // 判断是否来自eip系统
            let fromEip =
              document.referrer.indexOf("https://eip.konka.com/") > -1;
            // 登录成功后会将菜单存储在本地   如果本地缓存中存储了菜单列表数据 则直接使用
            if (
              localStorage.getItem(USER_MENU) &&
              (localStorage.getItem(USER_MENU) || []).length
            ) {
              // 递归遍历 给路由表数据新增一些属性
              const Router = routerTree(localStorage.getItem(USER_MENU));
              // 注意这里需要将这些报错提示页面放在路由表的最后面 因为路由匹配规则是前面path没匹配到的才会往下匹配！
              Router.push(
                {
                  path: "*",
                  redirect: "/404",
                  hidden: true,
                },
                {
                  path: "/404",
                  component: (resolve: any) =>
                    import("@/view/exception/404.vue"),
                }
              );
              // 递归生成布局组件中的菜单列表
              const layoutRouter = createMenuRouter(
                localStorage.getItem(USER_MENU)
              );
              Store.commit("route/LAYOUT_ROUTER", layoutRouter);
              Store.dispatch("route/GenerateRoutes", {
                Router,
              }).then(() => {
                // 1.根据roles权限生成可访问的路由表
                // 2.调用路由实例的addRoutes方法 添加可访问动态路由表
                router.addRoute(Store.getters.addRouters);
                // 如果需要重定向  则要在query参数中加redirect
                const redirect = decodeURIComponent(
                  (from.query.redirect || to.path) as string
                );
                Store.commit("route/SET_MENU", localStorage.getItem(USER_MENU)); // 用户路由权限

                // 从eip跳过来的直接放行
                if (fromEip) {
                  next();
                  /* 
                  业务场景：
                  用户在当前页面尝试刷新或重新进入，而这个页面本身就是通过重定向到达的
                  代码选择使用 next({ ...to, replace: true }) 
                  来替换当前的历史记录而不是添加新的记录
                  
                  这意味着用户的浏览器地址虽然不变，但是页面会被重新加载
                */
                } else if (to.path === redirect) {
                  console.log(
                    "------------------------replace搜索-----------------------------------"
                  );
                  // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
                  next({
                    ...to,
                    replace: true,
                  });
                } else {
                  // 跳转到目的路由
                  next({
                    path: redirect,
                  });
                }
              });
            } else {
              console.log(
                "--------------- localStorage.getItem(USER_MENU) 菜单不存在-----------------------"
              );
              next();
            }
            // 已存在菜单的情况下 跳非登录页 可以设置当前页面的权限列表 方便做按钮级别的权限匹配
          } else {
            console.log(
              "--------------- store.getters.userMenu.length !== 0------------------------"
            );
            Store.commit(
              "route/SET_PAGE_AUTH",
              utilGetPageAuths(getPathName(to), [])
            );
            next();
          }
        }
        /* 
      没有登录的情况
    */
      } else {
        // 在免登录白名单，直接进入
        if (WHITE_LIST.includes(to.name)) {
          next();
        } else {
          // cookies 里面 有LtpaToken  这里很可能是单点进来的
          if (
            cookies.isKey("LtpaToken") &&
            cookies.get("LtpaToken") !== "null"
          ) {
            let needAutoIndex = autoLoginRoutes.find((item) => {
              return item.path === to.path;
            });
            if (needAutoIndex) {
              // pro__Access-Token有值时，说明是从eip单点进来的  继续往下走
              if (
                localStorage.getItem(ACCESS_TOKEN) ||
                localStorage.getItem("pro__Access-Token")
              ) {
                console.log(
                  "------------------------pro__Access-Token有值时，继续往下走-----------------------------------"
                );
                next({ path: to.fullPath });
                return;
              }
              console.log(
                "------------------------未登录cookies 里面 有LtpaToken-----------------------------------"
              );
              // 否则走自动登录
              Store.dispatch("user/AutoLogin").then(() => {
                console.log("自动登录成功");
                next({ path: to.fullPath });
                return;
              });

              return;
            }
          }
          console.log(
            "------------------------报错3333-----------------------------------"
          );
          // 不是lbpm的页面
          if (location.href.indexOf("fdId") == -1) {
            console.log(
              "------------------------不是lbpm的页面-----------------------------------"
            );
            next({
              // path: '/user/login'
              path: "/start",
            });
          }

          nprogress.done(); // if current page is login will not trigger afterEach hook, so manually handle it
        }
      }
    }
  );
  return router;
};

export default routeSafe;
